/* File:        	MgMChannel.java
* Package:			org.esi.authz.comm
* Created:      	29-abr-2011
* Last Changed: 	0:08:10
* Author:       	Borja Urkizu borja.urquizu@tecnalia.com
*
*   
* History:
*  Revision 1.0.0.0  
* 
* Tecnalia Research and Innovation
*/
package com.tecnalia.authz.comm.channel;

import java.io.*;
import java.net.*;

import com.tecnalia.authz.common.log.PDPLog;
import com.tecnalia.authz.pdp.core.PDPEngine;
import com.tecnalia.authz.pdp.core.PDPInstances;
import com.tecnalia.comm.channel.IDChannel;

// TODO: Auto-generated Javadoc
/**
 * The Class MgMChannel.
 */
public class MgMDChannelImpl extends Thread implements IDChannel {
	   
   	/** The client. */
   	private Socket client = null;
	   
   	/** The in. */
   	private InputStream in = null;
	   
   	/** The os. */
   	private OutputStream os = null;
	   
   	/** The logger. */
   	public PDPLog logger = new PDPLog(this.getClass());	

	   /** The daemon. */
   	public PDPEngine daemon;
	   

		/* (non-Javadoc)
		 * @see org.esi.authz.comm.IDaemonChannel#run()
		 */
		@Override
	   public void Connect(Socket clientSocket) {
	     client = clientSocket;
	     try {
	      in = client.getInputStream();
	      os = client.getOutputStream();
	     } catch(Exception e1) {
	         try {
	            client.close();
	         }catch(Exception e) {
	        	 this.logger.info(e.getMessage());
	         }
	         return;
	     }
	     this.start();
	   }

	/* (non-Javadoc)
	 * @see org.esi.authz.comm.IDaemonChannel#run()
	 */
	@Override
	public void run() {
		PrintStream out=null;
//            try {
//                out=new PrintStream(os, true, "US-ASCII"); // Java 1.4+
//            } catch (UnsupportedEncodingException ex) {
                out=new PrintStream(os, true);
//            }

         while(true) {
                try {
                    /* If we don't have data in the System InputStream, we want
                       to ask to the user for an option. */
                    if (in.available()==0) {
                        out.println();
                        out.println("Please select one of the following:");
                        out.println("    1) PDP Start");
                        out.println("    2) PDP Shutdown");
                        out.println("    3) PDP Restart");
                        out.println("    4) PDP Status ");
                        out.println("    5) Disconect");
                        out.println("Enter Your choice: ");
                    }

                    /* Read an option from the client */
                    int x=in.read();

                    switch (x) {
                        /* If the socket was closed, we simply return */
                        case -1:
                            return;

                            /* Attempt to shutdown */
                        case '1':
                            out.println("Attempting a start...");
                            try {
                                //Register the daemon
                                if ( PDPInstances.getPdpDaemon() != null){
                                    out.println();
                                    out.println("PDP Instance already running");
                                    break;
                                }
                            	
                                //this.controller.shutdown();
                            	daemon = new PDPEngine();
                            	daemon.start();
                            } catch (IllegalStateException e) {
                                out.println();
                                out.println("Can't start now");
                                e.printStackTrace(out);
                            } catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
                            break;


                        /* Attempt to shutdown */
                        case '2':
                            out.println("Attempting a shutdown...");
                            try {
                                //this.controller.shutdown();
                            	daemon.cleanup();
                            	daemon = null;
                            	
                            } catch (IllegalStateException e) {
                                out.println();
                                out.println("Can't shutdown now");
                                e.printStackTrace(out);
                            }
                            break;

                        /* Attempt to reload */
                        case '3':
                            out.println("Attempting a reload...");
                            try {
                                //Stop the daemon
                            	daemon.cleanup();
                            	daemon = null;
                            	//Start the daemon
                            	daemon = new PDPEngine();
                            	daemon.start();                            	
                            } catch (IllegalStateException e) {
                                out.println();
                                out.println("Can't reload now");
                                e.printStackTrace(out);
                            } catch (Exception e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
                            break;


                        /* Create a directory (PR 30177 with 1.4.x and 1.5.0 */
                        case '4':
                            out.println("Not Implemented yet.... Have u got time?");
                            break;


                            /* Attempt to shutdown */
                        case '5':
                            out.println("Disconnecting...");
                            try {
                                //this.controller.shutdown();
                            	Thread.currentThread().interrupt() ;
                            	return;
                            	
                            } catch (IllegalStateException e) {
                                out.println();
                                out.println("Can't shutdown now");
                                e.printStackTrace(out);
                            }
                            break;

                        /* Discard any carriage return / newline characters */
                        case '\r':
                        case '\n':
                            break;

                        /* We got something that we weren't supposed to get */
                        default:
                            out.println("Unknown option '"+(char)x+"'");
                            break;

                    }

                /* If we get an IOException we return (disconnect) */
                } catch (IOException e) {
                	e.getMessage();
                	return;
                }
            }
    }

	/* (non-Javadoc)
	 * @see org.esi.authz.comm.IDaemonChannel#cleanup()
	 */
	@Override
	public void cleanup() {
		// TODO Auto-generated method stub
	}

}	
		
		
		/*Protocol reqSerialized = null;
		   try {
	        //Read from InputBuffer
			reqSerialized = (Protocol) ois.readObject();
			if ( PDPLog.logger.isDebugEnabled() ){
				for (Iterator<String> iterator = reqSerialized.Request.iterator(); iterator.hasNext();) {
					String reqPlainText = iterator.next();
					this.logger.debug("SERVER Request : " + reqPlainText); 
				}
			} 
			
			RequestContext[] requestContext = this.parseRequest(reqSerialized);			
			for (int i = 0; i < requestContext.length; i++) {
				ResponseContext responseAuthz = null;			
				
				//Evaluate the Request acording to the QueryMode
				int queryMode = reqSerialized.getQueryMode();
				
				//Evaluate the request in Simply Mode
				if(queryMode == XACMLConstants.XACML_QUERY_Simple){
					responseAuthz = DaemonImpl.evaluateRequest(requestContext[i]);
				}
				
				//Evaluate the request in Flexible Mode
				if(queryMode == XACMLConstants.XACML_QUERY_Flexible){
					responseAuthz = DaemonImpl.evaluateFlexibleRequest(requestContext[i]);
				}
				
				//Evaluate the request in Flexible Mode
				if(queryMode == XACMLConstants.XACML_QUERY_Strict){
					responseAuthz = DaemonImpl.evaluateStrictRequest(requestContext[i]);
				}
				
				
				ByteArrayOutputStream baos = new ByteArrayOutputStream();
				responseAuthz.marshall(baos);			 
				reqSerialized.Response.add(baos.toString());
				
				if ( PDPLog.logger.isDebugEnabled() ){
					this.logger.debug("SERVER Response : " + baos.toString()); 
				}
				
			}

			oos.writeObject(reqSerialized);
	        oos.flush();
	        
	        // close connections
	        ois.close();
	        oos.close();
	        client.close();
	        
	        
	      } catch(Exception e) {
	    	  this.logger.info(e.getMessage());
	      }       
	   }
	   
	   
	   
	   
	   private RequestContext[] parseRequest(Protocol reqSerialized){
		   RequestContext[] requestContext = new RequestContext[reqSerialized.Request.size()];  
		   int i = 0;
		   for (Iterator<String> iterator = reqSerialized.Request.iterator(); iterator.hasNext();) {
			   
			   String reqPlain = iterator.next();
			   //Parse the inputStream to an XACML Object
			   RequestContext request = RequestResponseContextFactory.createRequestCtx();
			   InputStream is = null;
			   try {
					is = new ByteArrayInputStream(reqPlain.getBytes("UTF-8"));
			   } catch (UnsupportedEncodingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				
				RequestCtx req = null;
				
				try {
					req = RequestCtx.getInstance(is);
				} catch (ParsingException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				request.set(org.jboss.security.xacml.interfaces.XACMLConstants.REQUEST_CTX, req);
				
				//Log the request
				
				ByteArrayOutputStream baos_p = new ByteArrayOutputStream();			
				try {
					request.marshall(baos_p);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				if ( PDPLog.logger.isDebugEnabled() ){
					this.logger.debug("SERVER Request - Parse : " + baos_p.toString());
				}
				
				requestContext[i] = request;
				i++;
				//req.encode(baos_p);				
				//this.Lpdp.info("SERVER Response - Parse : " + baos_p.toString());					
			
		}
		   

       	
			
			return requestContext;
	   }*/
	   
	   /*public ResponseContext Evaluate(RequestContext request) throws Exception {
	   
	        IDaemon sample = null;
	        ResponseContext res = null;
	        //Retrieve the configuration 
	        PDPConfiguration authzCfg = new PDPConfiguration();
	        try {
	        	//Create a PDP according to the configuration
				sample = new DaemonImpl(authzCfg);
				
				//Start the daemon
				sample.start();

				String[] recurso = {"recurso1"};

				//Create the list to hold the request
				res = sample.evaluateRequest(request);


	        }
	        catch (Throwable t) {
	            t.printStackTrace(System.err);
	            
	            if (sample != null) {
	                sample.cleanup();
	            }
	        }
	        
			return res;	        

	    	
	    }	

	   
	   
	}*/
